package maggames.core.visual;

import java.awt.*;

import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;

import maggames.core.GameMove;
import maggames.core.Piece;
import maggames.core.base.BaseSwingInterface;

public class VisualPiece extends JPanel implements Runnable {

	private static final long serialVersionUID = 1L;
	
	private Piece piece;
	
	private Point initialLocation = null;
	private boolean isDragging = false;
	private boolean special = false;
	private Color color1 = Color.BLUE;
	private Color color2 = Color.CYAN;
	private Color outline = Color.BLACK;
	private VisualSpace space = null;
	private Thread runner = null;
	private boolean delete = false;
	private boolean deleted = false;
	private float timer = 0.0f;

	/**
	 * This is the default constructor
	 */
	public VisualPiece() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		runner = new Thread(this);
		this.setOpaque(false);
		this.setBackground(Color.RED);
		this.setSize(30, 30);
		this.setLayout(null);
		this.setPreferredSize(new Dimension(30, 30));
		this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.addMouseListener(new java.awt.event.MouseAdapter() {   
			public void mouseReleased(java.awt.event.MouseEvent e) {    
				isDragging = false;
				VisualPiece p = (VisualPiece)e.getSource();
				BaseSwingInterface b = (BaseSwingInterface)p.getParent();
				VisualSpace s = b.getSpaceAt(p.getCenter());
				b.setComponentZOrder(p, 1);
				p.repaint();
				
				Point oldLocation = new Point(GameMove.OFFBOARD, GameMove.OFFBOARD);
				if(p.getSpace()!=null) {
					oldLocation = p.getSpace().getBoardLocation();
				}
				
				
				boolean remove = false;
				if(s!=null) {
					if(s.getVisualPiece()==p && e.isShiftDown()) {
						remove = true;
					}
					else if(s.getVisualPiece()==null || s.getVisualPiece() == p) {
						p.setSpace(s);
						GameMove m = new GameMove();
						m.setPiece(p.getPiece());
						m.setFirstPoint(oldLocation.x, oldLocation.y);
						m.setDestPoint(s.getBoardLocation().x, s.getBoardLocation().y);
						b.makeMove(m);
						
					}
					else if(s.getVisualPiece()!=null) {
						p.setLocation(initialLocation);
					}
				}
				else {
					if(p.getSpace() != null) {
						VisualSpace space = p.getSpace();
						p.setLocation(space.getCenter().x -p.getWidth()/2, space.getCenter().y -p.getHeight()/2);
					}
				}
				if(remove) {
					GameMove m = new GameMove();
					m.setPiece(p.getPiece());
					m.setFirstPoint(oldLocation.x, oldLocation.y);
					m.setDestPoint(GameMove.OFFBOARD, GameMove.OFFBOARD);
					b.makeMove(m);
					p.delete();
				}
			}
			public void mousePressed(java.awt.event.MouseEvent e) {
				isDragging = true;
				VisualPiece p = (VisualPiece)e.getSource();
				initialLocation = p.getLocation();
				BaseSwingInterface b = (BaseSwingInterface)p.getParent();
				p.setLocation(p.getX()+e.getX()-p.getWidth()/2, p.getY()+e.getY()-p.getHeight()/2);	
				b.setComponentZOrder(p, 0);
				p.repaint();
			}
		});
		this.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
			public void mouseDragged(java.awt.event.MouseEvent e) {
				VisualPiece p = (VisualPiece)e.getSource();
				int dx = e.getX()-p.getWidth()/2;
				int dy = e.getY()-p.getWidth()/2;
				p.setLocation(p.getX()+dx, p.getY()+dy);
				p.getParent().repaint();
			}
		});
	}
	
	public void paintComponent(Graphics g) {
		if(deleted) {return;}
		
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		GradientPaint gp = new GradientPaint( getWidth()/5, getHeight()/5, getColor2(), 
											  getWidth(), getHeight(), getColor1(), 
											  true );
		g2d.setPaint(gp);
		BasicStroke s = new BasicStroke(2);
		g2d.setStroke(s);
		
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		if(this.isDragging){
			g2d.setColor(Color.BLACK);
			g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
			g2d.fillOval(4,4,this.getWidth()-11, this.getHeight()-11);
			g2d.setComposite(AlphaComposite.SrcOver);
			g2d.setPaint(gp);
			g2d.fillOval(1,1,this.getWidth()-11, this.getHeight()-11);
			g2d.setColor(Color.BLACK);
			g2d.drawOval(1,1,this.getWidth()-11, this.getHeight()-11);
		}
		else {
			g2d.fillOval(5,5,this.getWidth()-11, this.getHeight()-11);
			g2d.setColor(outline);
			g2d.drawOval(5,5,this.getWidth()-11, this.getHeight()-11);
			
		}
		
	}
	
	public Point getCenter() {
		return new Point(this.getX()+this.getWidth()/2,this.getY()+this.getHeight()/2);
	}

	public VisualSpace getSpace() {
		return space;
	}

	public void setSpace(VisualSpace space) {
		if(space==null && deleted) {
			getSpace().setVisualPiece(null);
		}
		else if (space==null) {
			getSpace().setVisualPiece(null);
			this.space = null;
		}
		else if(space.getVisualPiece()==null || space.getVisualPiece() == this) {
			VisualSpace temp = this.space;
			this.space = space;
			space.setVisualPiece(this);
			this.setLocation(space.getCenter().x -this.getWidth()/2, space.getCenter().y -this.getHeight()/2);
			if(temp!=null) {
				temp.setVisualPiece(null);
			}
		}
	}

	public Color getColor1() {
		return color1;
	}

	public void setColor1(Color color1) {
		this.color1 = color1;
	}

	public Color getColor2() {
		return color2;
	}

	public void setColor2(Color color2) {
		this.color2 = color2;
	}

	public boolean isSpecial() {
		return special;
	}

	public void setSpecial(boolean special) {
		this.special = special;
	}
	
	public boolean shouldRemove() {
		return deleted;
	}
	
	public void delete() {
		delete = true;
		runner.start();
	}
	
	public void moveTo(VisualSpace s) {
		
	}

	public void run() {
		float deleteTime = 0.3f;
		float progress = 0.0f;
		while( delete ) {
			timer += 0.01f;
			progress = (deleteTime-timer)/deleteTime;
			if(timer < deleteTime) {
				setColor1(new Color(color1.getRed(), color1.getGreen(), color1.getBlue(), (int) (progress*255)));
				setColor2(new Color(color2.getRed(), color2.getGreen(), color2.getBlue(), (int) (progress*255)));
				setOutline(new Color(outline.getRed(), outline.getGreen(), outline.getBlue(), (int) (progress*255)));
				
				setLocation(getX()-(int)(progress*10),getY()-(int)(progress*10));
				setSize(getWidth()+(int)(progress*20),getHeight()+(int)(progress*20));
				
				repaint();
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			else {
				deleted = true;
				delete = false;
				setSpace(null);
				setSize(0,0);
				setLocation(0,0);
				return;
			}
		}
	}

	public Color getOutline() {
		return outline;
	}

	public void setOutline(Color outline) {
		this.outline = outline;
	}

	public Piece getPiece() {
		return piece;
	}

	public void setPiece(Piece piece) {
		if(piece==Piece.P2) {
			setColor1(Color.RED);
			setColor2(Color.ORANGE);
		}
		this.piece = piece;
	}

	/**
	 * @return the initialLocation
	 */
	public Point getInitialLocation() {
		return initialLocation;
	}

	/**
	 * @param initialLocation the initialLocation to set
	 */
	public void setInitialLocation(Point initialLocation) {
		this.initialLocation = initialLocation;
	}
	
}  //  @jve:decl-index=1:visual-constraint="4111,116"
